#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Maven安装器 - 通用版本
使用wxPython框架，具有更好的跨平台兼容性
功能：
1. 自动检测操作系统
2. 获取Maven版本列表
3. 提供GUI界面选择版本和安装目录
4. 自动下载和安装Maven
5. 兼容更多macOS版本和系统环境
"""

import platform
import requests
import os
import sys
import subprocess
import threading
import zipfile
import tarfile
import shutil
import warnings
from datetime import datetime
import time
import json

# 忽略SSL警告
warnings.filterwarnings('ignore', message='urllib3 v2 only supports OpenSSL 1.1.1+')

# 使用最新稳定的Maven版本
MAVEN_VERSION = "3.9.11"
MAVEN_DOWNLOAD_URL = f"https://dlcdn.apache.org/maven/maven-3/{MAVEN_VERSION}/binaries/apache-maven-{MAVEN_VERSION}-bin.tar.gz"
MAVEN_DOWNLOAD_URL_WIN = f"https://dlcdn.apache.org/maven/maven-3/{MAVEN_VERSION}/binaries/apache-maven-{MAVEN_VERSION}-bin.zip"

# 尝试导入wxPython
try:
    import wx
    import wx.adv
    import wx.html
    WX_AVAILABLE = True
except ImportError:
    print("无法导入wxPython，将使用命令行界面")
    WX_AVAILABLE = False

def detect_os():
    """检测操作系统信息"""
    system = platform.system().lower()
    machine = platform.machine().lower()
    
    os_info = {
        'system': system,
        'machine': machine,
        'platform': platform.platform(),
        'version': platform.version()
    }
    
    # 确定下载文件扩展名
    if system == 'windows':
        os_info['extension'] = 'zip'
        os_info['binary_name'] = 'mvn.cmd'
        os_info['download_url'] = MAVEN_DOWNLOAD_URL_WIN
    else:  # macOS/Linux
        os_info['extension'] = 'tar.gz'
        os_info['binary_name'] = 'mvn'
        os_info['download_url'] = MAVEN_DOWNLOAD_URL
    
    return os_info

def get_default_install_path(os_info):
    """获取默认安装路径（用户目录下，避免权限问题）"""
    home_dir = os.path.expanduser("~")
    
    if os_info['system'] == 'windows':
        return os.path.join(home_dir, 'Maven')
    else:  # macOS/Linux
        return os.path.join(home_dir, 'maven')

def download_file(url, filepath, progress_callback=None):
    """下载文件"""
    print(f"开始下载: {url}")
    response = requests.get(url, stream=True, timeout=30)
    response.raise_for_status()
    
    total_size = int(response.headers.get('content-length', 0))
    downloaded_size = 0
    start_time = time.time()
    
    with open(filepath, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)
            downloaded_size += len(chunk)
            
            if total_size > 0:
                progress = (downloaded_size / total_size) * 100
                elapsed_time = time.time() - start_time
                
                if elapsed_time > 0:
                    speed = downloaded_size / elapsed_time / 1024  # KB/s
                    
                    # 如果提供了回调函数，调用它
                    if progress_callback:
                        progress_callback(progress, downloaded_size, total_size, speed)
                    else:
                        print(f"\r下载进度: {progress:.1f}% ({downloaded_size//1024//1024}MB/{total_size//1024//1024}MB) - {speed:.1f} KB/s", end='')
                else:
                    if progress_callback:
                        progress_callback(progress, downloaded_size, total_size, 0)
                    else:
                        print(f"\r下载进度: {progress:.1f}% ({downloaded_size//1024//1024}MB/{total_size//1024//1024}MB)", end='')
    
    print("\n下载完成!")

def extract_file(filepath, extract_dir):
    """解压文件"""
    print("开始解压...")
    if filepath.endswith('.zip'):
        with zipfile.ZipFile(filepath, 'r') as zip_ref:
            zip_ref.extractall(extract_dir)
    elif filepath.endswith('.tar.gz'):
        with tarfile.open(filepath, 'r:gz') as tar_ref:
            tar_ref.extractall(extract_dir)
    print("解压完成!")

def show_environment_setup_cli(maven_home, os_info):
    """显示环境变量配置信息（命令行版本）"""
    bin_path = os.path.join(maven_home, "bin")
    
    print("\nMaven安装完成!")
    print(f"\n安装路径: {maven_home}")
    print("\n请手动配置环境变量：")
    
    if os_info['system'] == 'windows':
        print(f"\nWindows:")
        print(f"set MAVEN_HOME={maven_home}")
        print(f"set PATH=%PATH%;{bin_path}")
    else:
        print(f"\nmacOS/Linux:")
        print(f"export MAVEN_HOME={maven_home}")
        print(f"export PATH=$PATH:{bin_path}")
        print(f"\n或者将以下内容添加到 ~/.bashrc 或 ~/.zshrc:")
        print(f"export MAVEN_HOME={maven_home}")
        print(f"export PATH=$PATH:{bin_path}")
    
    print("\n配置完成后，请重新打开终端并运行 'mvn --version' 验证安装。")

def install_maven_cli():
    """命令行版本的安装流程"""
    print("=== Maven安装器 (命令行版本) ===\n")
    
    # 检测操作系统
    os_info = detect_os()
    print(f"检测到操作系统: {os_info['platform']}")
    print(f"系统架构: {os_info['machine']}\n")
    
    # 使用固定版本
    selected_version = MAVEN_VERSION
    print(f"使用稳定版本: Maven {selected_version}")
    
    # 选择安装目录
    default_path = get_default_install_path(os_info)
    install_path = default_path
    try:
        user_path = input(f"请输入安装目录 (默认: {default_path}): ").strip()
        if user_path:
            install_path = user_path
    except:
        print(f"使用默认安装路径: {default_path}")
    
    print(f"安装目录: {install_path}")
    print()
    
    # 确认安装
    confirm = "y"  # 默认确认
    try:
        confirm = input("确认开始安装? (y/N): ").strip().lower()
    except:
        print("使用默认选择: y")
    
    if confirm in ['y', 'yes'] or not confirm:
        try:
            print(f"开始安装Maven {selected_version}")
            print(f"安装目录: {install_path}")
            
            # 创建安装目录
            os.makedirs(install_path, exist_ok=True)
            
            # 下载Maven
            download_url = os_info['download_url']
            print(f"下载URL: {download_url}")
            
            # 下载文件
            filename = f"apache-maven-{selected_version}-bin.{os_info['extension']}"
            filepath = os.path.join(install_path, filename)
            
            download_file(download_url, filepath)
            
            # 解压文件
            extract_file(filepath, install_path)
            
            # 移动文件到最终位置
            extracted_dir = os.path.join(install_path, f"apache-maven-{selected_version}")
            final_dir = os.path.join(install_path, "maven")
            
            if os.path.exists(final_dir):
                shutil.rmtree(final_dir)
            shutil.move(extracted_dir, final_dir)
            
            # 清理下载文件
            os.remove(filepath)
            
            print("Maven安装完成!")
            
            # 显示环境变量配置信息
            show_environment_setup_cli(final_dir, os_info)
            
        except Exception as e:
            print(f"安装失败: {str(e)}")
    else:
        print("安装已取消")

# wxPython GUI 实现
if WX_AVAILABLE:
    class DownloadThread(threading.Thread):
        """下载线程"""
        def __init__(self, url, filepath, progress_callback):
            super().__init__()
            self.url = url
            self.filepath = filepath
            self.progress_callback = progress_callback
            self.is_cancelled = False
            self.daemon = True
        
        def run(self):
            try:
                wx.CallAfter(self.progress_callback, 0, 0, 0, 0, "开始下载...")
                
                response = requests.get(self.url, stream=True, timeout=30)
                response.raise_for_status()
                
                total_size = int(response.headers.get('content-length', 0))
                downloaded_size = 0
                start_time = time.time()
                
                with open(self.filepath, 'wb') as f:
                    for chunk in response.iter_content(chunk_size=8192):
                        if self.is_cancelled:
                            wx.CallAfter(self.progress_callback, 0, 0, 0, 0, "下载已取消")
                            return
                        
                        f.write(chunk)
                        downloaded_size += len(chunk)
                        
                        if total_size > 0:
                            progress = (downloaded_size / total_size) * 100
                            elapsed_time = time.time() - start_time
                            
                            if elapsed_time > 0:
                                speed = downloaded_size / elapsed_time / 1024  # KB/s
                                status = f"下载中... {downloaded_size//1024//1024}MB/{total_size//1024//1024}MB"
                                wx.CallAfter(self.progress_callback, progress, downloaded_size, total_size, speed, status)
                
                wx.CallAfter(self.progress_callback, 100, total_size, total_size, 0, "下载完成")
                
            except Exception as e:
                wx.CallAfter(self.progress_callback, 0, 0, 0, 0, f"下载失败: {str(e)}")
        
        def cancel(self):
            self.is_cancelled = True
    
    class ExtractThread(threading.Thread):
        """解压线程"""
        def __init__(self, filepath, extract_dir, callback):
            super().__init__()
            self.filepath = filepath
            self.extract_dir = extract_dir
            self.callback = callback
            self.daemon = True
        
        def run(self):
            try:
                wx.CallAfter(self.callback, "开始解压...")
                
                if self.filepath.endswith('.zip'):
                    with zipfile.ZipFile(self.filepath, 'r') as zip_ref:
                        zip_ref.extractall(self.extract_dir)
                elif self.filepath.endswith('.tar.gz'):
                    with tarfile.open(self.filepath, 'r:gz') as tar_ref:
                        tar_ref.extractall(self.extract_dir)
                
                wx.CallAfter(self.callback, "解压完成")
                
            except Exception as e:
                wx.CallAfter(self.callback, f"解压失败: {str(e)}")
    
    class MavenInstallerFrame(wx.Frame):
        """Maven安装器主窗口"""
        def __init__(self):
            super().__init__(None, title="Maven安装器", size=(600, 500))
            
            self.os_info = detect_os()
            self.install_path = get_default_install_path(self.os_info)
            self.download_thread = None
            self.extract_thread = None
            
            # 创建界面
            self.init_ui()
            self.Center()
            
            # 初始化日志
            self.log(f"检测到操作系统: {self.os_info['platform']}")
            self.log(f"系统架构: {self.os_info['machine']}")
            self.log(f"使用Maven版本: {MAVEN_VERSION}")
        
        def init_ui(self):
            """初始化界面"""
            panel = wx.Panel(self)
            
            # 创建垂直布局
            main_sizer = wx.BoxSizer(wx.VERTICAL)
            
            # 系统信息
            system_box = wx.StaticBox(panel, label="系统信息")
            system_sizer = wx.StaticBoxSizer(system_box, wx.VERTICAL)
            
            system_label = wx.StaticText(panel, label=f"操作系统: {self.os_info['platform']}")
            system_sizer.Add(system_label, 0, wx.ALL, 5)
            
            arch_label = wx.StaticText(panel, label=f"架构: {self.os_info['machine']}")
            system_sizer.Add(arch_label, 0, wx.ALL, 5)
            
            main_sizer.Add(system_sizer, 0, wx.EXPAND | wx.ALL, 10)
            
            # Maven版本
            version_box = wx.StaticBox(panel, label="Maven版本")
            version_sizer = wx.StaticBoxSizer(version_box, wx.VERTICAL)
            
            version_label = wx.StaticText(panel, label=f"版本: {MAVEN_VERSION}")
            version_sizer.Add(version_label, 0, wx.ALL, 5)
            
            main_sizer.Add(version_sizer, 0, wx.EXPAND | wx.ALL, 10)
            
            # 安装目录
            path_box = wx.StaticBox(panel, label="安装目录")
            path_sizer = wx.StaticBoxSizer(path_box, wx.HORIZONTAL)
            
            self.path_text = wx.TextCtrl(panel, value=self.install_path, style=wx.TE_PROCESS_ENTER)
            path_sizer.Add(self.path_text, 1, wx.EXPAND | wx.ALL, 5)
            
            browse_btn = wx.Button(panel, label="浏览")
            browse_btn.Bind(wx.EVT_BUTTON, self.on_browse)
            path_sizer.Add(browse_btn, 0, wx.ALL, 5)
            
            main_sizer.Add(path_sizer, 0, wx.EXPAND | wx.ALL, 10)
            
            # 进度条
            progress_box = wx.StaticBox(panel, label="安装进度")
            progress_sizer = wx.StaticBoxSizer(progress_box, wx.VERTICAL)
            
            self.progress_bar = wx.Gauge(panel, range=100, style=wx.GA_HORIZONTAL | wx.GA_SMOOTH)
            progress_sizer.Add(self.progress_bar, 0, wx.EXPAND | wx.ALL, 5)
            
            self.status_label = wx.StaticText(panel, label="准备就绪")
            progress_sizer.Add(self.status_label, 0, wx.ALL, 5)
            
            main_sizer.Add(progress_sizer, 0, wx.EXPAND | wx.ALL, 10)
            
            # 日志区域
            log_box = wx.StaticBox(panel, label="安装日志")
            log_sizer = wx.StaticBoxSizer(log_box, wx.VERTICAL)
            
            self.log_text = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL)
            log_sizer.Add(self.log_text, 1, wx.EXPAND | wx.ALL, 5)
            
            main_sizer.Add(log_sizer, 1, wx.EXPAND | wx.ALL, 10)
            
            # 按钮
            button_sizer = wx.BoxSizer(wx.HORIZONTAL)
            
            self.install_btn = wx.Button(panel, label="开始安装")
            self.install_btn.Bind(wx.EVT_BUTTON, self.on_install)
            button_sizer.Add(self.install_btn, 0, wx.RIGHT, 5)
            
            self.cancel_btn = wx.Button(panel, label="取消")
            self.cancel_btn.Bind(wx.EVT_BUTTON, self.on_cancel)
            self.cancel_btn.Disable()
            button_sizer.Add(self.cancel_btn, 0)
            
            main_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.ALL, 10)
            
            panel.SetSizer(main_sizer)
        
        def on_browse(self, event):
            """浏览按钮事件处理"""
            dlg = wx.DirDialog(self, "选择Maven安装目录", defaultPath=self.install_path,
                              style=wx.DD_DEFAULT_STYLE)
            
            if dlg.ShowModal() == wx.ID_OK:
                self.install_path = dlg.GetPath()
                self.path_text.SetValue(self.install_path)
            
            dlg.Destroy()
        
        def on_install(self, event):
            """安装按钮事件处理"""
            self.install_path = self.path_text.GetValue()
            
            if not self.install_path:
                wx.MessageBox("请选择安装目录", "错误", wx.OK | wx.ICON_ERROR)
                return
            
            # 确认安装
            dlg = wx.MessageDialog(
                self,
                f"确定要安装Maven {MAVEN_VERSION} 到 {self.install_path} 吗？",
                "确认安装",
                wx.YES_NO | wx.ICON_QUESTION
            )
            
            if dlg.ShowModal() == wx.ID_YES:
                self.install_btn.Disable()
                self.cancel_btn.Enable()
                self.progress_bar.SetValue(0)
                self.status_label.SetLabel("准备中...")
                
                # 开始安装流程
                self.start_installation()
            
            dlg.Destroy()
        
        def on_cancel(self, event):
            """取消按钮事件处理"""
            if self.download_thread and self.download_thread.is_alive():
                self.download_thread.cancel()
            
            self.log("安装已取消")
            self.install_btn.Enable()
            self.cancel_btn.Disable()
        
        def log(self, message):
            """添加日志消息"""
            timestamp = datetime.now().strftime('%H:%M:%S')
            self.log_text.AppendText(f"[{timestamp}] {message}\n")
        
        def update_progress(self, progress, downloaded, total, speed, status):
            """更新进度条和状态"""
            self.progress_bar.SetValue(int(progress))
            self.status_label.SetLabel(status)
            
            if status == "下载完成":
                self.start_extraction()
        
        def start_installation(self):
            """开始安装流程"""
            try:
                # 创建安装目录
                os.makedirs(self.install_path, exist_ok=True)
                
                # 下载Maven
                download_url = self.os_info['download_url']
                self.log(f"下载URL: {download_url}")
                
                # 下载文件
                filename = f"apache-maven-{MAVEN_VERSION}-bin.{self.os_info['extension']}"
                self.filepath = os.path.join(self.install_path, filename)
                
                # 创建下载线程
                self.download_thread = DownloadThread(download_url, self.filepath, self.update_progress)
                self.download_thread.start()
                
            except Exception as e:
                self.log(f"安装准备失败: {str(e)}")
                self.install_btn.Enable()
                self.cancel_btn.Disable()
        
        def start_extraction(self):
            """开始解压"""
            self.extract_thread = ExtractThread(self.filepath, self.install_path, self.extraction_callback)
            self.extract_thread.start()
        
        def extraction_callback(self, message):
            """解压回调"""
            self.log(message)
            
            if message == "解压完成":
                self.finish_installation()
            elif message.startswith("解压失败"):
                self.install_btn.Enable()
                self.cancel_btn.Disable()
        
        def finish_installation(self):
            """完成安装"""
            try:
                # 移动文件到最终位置
                extracted_dir = os.path.join(self.install_path, f"apache-maven-{MAVEN_VERSION}")
                final_dir = os.path.join(self.install_path, "maven")
                
                if os.path.exists(final_dir):
                    shutil.rmtree(final_dir)
                shutil.move(extracted_dir, final_dir)
                
                # 清理下载文件
                os.remove(self.filepath)
                
                self.log("Maven安装完成！")
                self.status_label.SetLabel("安装完成")
                
                # 显示环境变量配置信息
                self.show_environment_setup(final_dir)
                
            except Exception as e:
                self.log(f"安装失败: {str(e)}")
            finally:
                self.install_btn.Enable()
                self.cancel_btn.Disable()
        
        def show_environment_setup(self, maven_home):
            """显示环境变量配置信息"""
            bin_path = os.path.join(maven_home, "bin")
            
            env_info = f"""
Maven安装完成！

安装路径: {maven_home}

请手动配置环境变量：

Windows:
set MAVEN_HOME={maven_home}
set PATH=%PATH%;{bin_path}

macOS/Linux:
export MAVEN_HOME={maven_home}
export PATH=$PATH:{bin_path}

或者将以下内容添加到 ~/.bashrc 或 ~/.zshrc:
export MAVEN_HOME={maven_home}
export PATH=$PATH:{bin_path}

配置完成后，请重新打开终端并运行 'mvn --version' 验证安装。
"""
            
            # 显示配置信息对话框
            dlg = wx.MessageDialog(
                self,
                env_info,
                "环境变量配置",
                wx.OK | wx.ICON_INFORMATION
            )
            dlg.ShowModal()
            dlg.Destroy()
            
            # 创建复制按钮对话框
            copy_dlg = wx.MessageDialog(
                self,
                "是否复制环境变量配置到剪贴板？",
                "复制配置",
                wx.YES_NO | wx.ICON_QUESTION
            )
            
            if copy_dlg.ShowModal() == wx.ID_YES:
                if wx.TheClipboard.Open():
                    wx.TheClipboard.SetData(wx.TextDataObject(env_info))
                    wx.TheClipboard.Close()
                    wx.MessageBox("环境变量配置信息已复制到剪贴板", "成功", wx.OK | wx.ICON_INFORMATION)
            
            copy_dlg.Destroy()

def main():
    # 尝试使用wxPython GUI，如果失败则使用命令行
    if WX_AVAILABLE:
        try:
            app = wx.App(False)
            frame = MavenInstallerFrame()
            frame.Show()
            app.MainLoop()
        except Exception as e:
            print(f"GUI启动失败: {str(e)}")
            print("切换到命令行模式")
            install_maven_cli()
    else:
        install_maven_cli()

if __name__ == "__main__":
    main()
